﻿using System;
using System.Collections.Generic;
using System.Linq;
using CommonLibrary;
using FileLibrary;
using FileLibrary.Models;
using CommonLibrary.Helpers;
using FileLibrary.Enums;
using GeneticSharpDemo.Models;

namespace GeneticSharpDemo.Data
{
    public class DataManage
    {
        public static DataManage Instance = new Lazy<DataManage>(() => new DataManage()).Value;

        public int IsWashBeforeRepair = 1;

        /// <summary>
        /// key:JobName
        /// </summary>
        public Dictionary<string, JobInfo> JobInfoDic { get; set; }

        public List<Track> Tracks { get; set; }

        public List<Track> StoreTracks { get; set; }
        public List<Path> Paths { get; set; }

        public List<MaintenancePlan> MaintenancePlans { get; set; }

        public List<TrainStartInfo> TrainStartInfos { get; set; }

        public List<TrainPlan> TrainPlans { get; set; }

        public List<MaintenanceProgram> MaintenancePrograms { get; set; }
        public List<MaintenanceSequence> MaintenanceSequences { get; set; }
        public List<TimeConfig> TimeConfigs { get; set; }
        public int DPathTime => TimeConfigs[0].Time;
        public int JPathTime => TimeConfigs[1].Time;
        public int NightDutyStartTime => TimeConfigs[2].Time.GetTimePosByHour();
        public int NightDutyEndTime => TimeConfigs[3].Time.GetTimePosByHour();
        public int RepairDutyStartTime => TimeConfigs[4].Time.GetTimePosByHour();

        /// <summary>
        /// 任务队列
        /// 按照jobId+ProcId为索引
        /// 
        /// </summary>
        public List<JobAndProc> JobAndProcList { get; set; }

        private DataManage()
        {
            InitDataList();
            CalProcExistList();
            CalJobInfoDic();
        }

        private void CalJobInfoDic()
        {
            JobInfoDic = new Dictionary<string, JobInfo>();
            var index = 0;
            ////通过检修单整理任务
            //foreach (var maintenancePlan in MaintenancePlans)
            //{
            //    var jobName = maintenancePlan.TrainId;
            //    index = AddJobInfoDic(jobName, index, maintenancePlan);
            //    var jobInfo = JobInfoDic[jobName];
            //    SetJobProcTrackNameAndTime(maintenancePlan, jobInfo);
            //}

            //通过开行单整理任务
            foreach (var trainPlan in TrainPlans)
            {
                var jobName = trainPlan.TrainId;
                var job = new JobInfo(jobName, ProcList)
                {
                    JobId = index++,
                };

                var timePos = trainPlan.TimeInDepot.GetTimePosByTimeStr();
                if (timePos >= 0)
                {
                    job.StartTime = timePos;
                    job.DepotIn = true;
                }

                timePos = trainPlan.TimeOutDepot.GetTimePosByTimeStr();
                if (timePos >= 0)
                {
                    job.EndTime = timePos;
                    job.DepotOut = true;
                }

                job.TrainGroupType = trainPlan.TrainGroupTypeEnum;

                foreach (var maintenancePlan in MaintenancePlans.Where(maintenancePlan => maintenancePlan.TrainId == jobName))
                {
                    SetJobProcTrackNameAndTime(maintenancePlan, job);
                }

                JobInfoDic.Add(jobName, job);
            }

            JobQty = JobInfoDic.Count;

            JobAndProcList = new List<JobAndProc>();
            index = 0;

            var washProc = ProcList.First(x => x.TrackType == TrackTypeEnum.Wash);
            foreach (var jobInfo in JobInfoDic)
            {
                var value = jobInfo.Value;

                for (int i = 0; i < ProcList.Count; i++)
                {
                    var proc = ProcList[i];
                    if (!proc.IsExist) continue;
                    var time = value.ProcInfos[i].Time;
                    if (time <= 0) continue;
                    if (IsWashBeforeRepair == 1 && ProcList[i].TrackType == TrackTypeEnum.Wash)
                    {

                    }
                    else if (IsWashBeforeRepair == 1 && ProcList[i].TrackType == TrackTypeEnum.Repair)
                    {
                        JobAndProcList.Add(new JobAndProc
                        {
                            Index = index++,
                            JobInfo = value,
                            Proc = proc,
                            PreProc = washProc
                        });
                    }
                    else
                    {
                        JobAndProcList.Add(new JobAndProc
                        {
                            Index = index++,
                            JobInfo = value,
                            Proc = proc,
                        });
                    }
                }
            }
        }

        private void SetJobProcTrackNameAndTime(MaintenancePlan maintenancePlan, JobInfo jobInfo)
        {
            if (!string.IsNullOrEmpty(maintenancePlan.MaintenanceName)) //防御检修项目不填写情况
            {
                //通过检修项目获得对应的检修时间，通过检修规范表格维护
                var maintenanceProgram = MaintenancePrograms.First(x => x.MaintenanceEnum == maintenancePlan.MaintenanceEnum);
                var maintenanceProgramTime = maintenanceProgram.Time;
                var procIndex = ProcList.FindIndex(x => x.TrackType == maintenanceProgram.TrackTypeEnum);
                if (procIndex >= 0)
                {
                    jobInfo.ProcInfos[procIndex].Time += maintenanceProgramTime;//累计同股道任务作业时间
                }

                jobInfo.ProcInfos[procIndex].TrackName = maintenancePlan.MaintenanceTrackName;
                jobInfo.ProcInfos[procIndex].StartTime = maintenancePlan.MaintenanceStartTime.GetTimePosByTimeStr();
                jobInfo.ProcInfos[procIndex].EndTime = maintenancePlan.MaintenanceStopTime.GetTimePosByTimeStr();
            }
        }

        //private int AddJobInfoDic(string jobName, int index, MaintenancePlan maintenancePlan)
        //{
        //    if (JobInfoDic.ContainsKey(jobName)) return index;
        //    var job = new JobInfo(jobName, ProcList.Count)
        //    {
        //        JobId = index++,
        //    };

        //    SetJobDepotInfo(maintenancePlan, job);
        //    JobInfoDic.Add(jobName, job);

        //    return index;
        //}

        ///// <summary>
        ///// 通过开行计划整理任务的起始和终止时间
        ///// </summary>
        ///// <param name="maintenancePlan"></param>
        ///// <param name="job"></param>
        //private void SetJobDepotInfo(MaintenancePlan maintenancePlan, JobInfo job)
        //{
        //    //通过开行计划整理任务的起始和终止时间
        //    var trainPlan = TrainPlans.FirstOrDefault(x => x.TrainId == maintenancePlan.TrainId);
        //    if (trainPlan == null) return;
        //    var timePos = trainPlan.TimeInDepot.GetTimePosByTimeStr();
        //    if (timePos >= 0)
        //    {
        //        job.StartTime = timePos;
        //        job.DepotIn = true;
        //    }

        //    timePos = trainPlan.TimeOutDepot.GetTimePosByTimeStr();
        //    if (timePos >= 0)
        //    {
        //        job.EndTime = timePos;
        //        job.DepotOut = true;
        //    }
        //}

        public int JobQty { get; set; }

        /// <summary>
        /// 初始化数据列表
        /// </summary>
        private void InitDataList()
        {
            //优先初始化时间配置，后续配置可能依赖时间配置进行换算
            TimeConfigs = FileManage.Instance.FileModes.Values.Where(x => x is TimeConfig).Cast<TimeConfig>().ToList();

            Sys.PlanStartHourCnt = TimeConfigs[2].Time;
            Sys.PlanStopHourCnt = TimeConfigs[3].Time;

            Tracks = FileManage.Instance.FileModes.Values.Where(x => x is Track).Cast<Track>().ToList();
            StoreTracks = FileManage.Instance.FileModes.Values.Where(x => x is Track && ((Track)x).TrackTypeEnum == TrackTypeEnum.Store).Cast<Track>().ToList();
            Paths = FileManage.Instance.FileModes.Values.Where(x => x is Path).Cast<Path>().ToList();

            // TrainPlans = FileManage.Instance.FileModes.Values.Where(x => x is TrainPlan).Cast<TrainPlan>().ToList();
            TrainPlans = FileManage.Instance.FileModes.Values.Where(x => x is TrainPlan && ((TrainPlan)x).Index > 0).Cast<TrainPlan>().ToList();//调试
            MaintenancePlans = FileManage.Instance.FileModes.Values.Where(x => x is MaintenancePlan).Cast<MaintenancePlan>()
                .ToList();
            TrainStartInfos = FileManage.Instance.FileModes.Values.Where(x => x is TrainStartInfo).Cast<TrainStartInfo>()
                .ToList();
            MaintenancePrograms = FileManage.Instance.FileModes.Values.Where(x => x is MaintenanceProgram)
                .Cast<MaintenanceProgram>().ToList();
            MaintenanceSequences = FileManage.Instance.FileModes.Values.Where(x => x is MaintenanceSequence)
                .Cast<MaintenanceSequence>().ToList();
        }


        /// <summary>
        /// 计算模型工序，减少搜索空间
        /// </summary>
        private void CalProcExistList()
        {
            //计算工序，根据股道类型获得所有工序类型。如果检修项目对应的股道类型存在，工序存在。
            var i = 0;
            var enumType = typeof(TrackTypeEnum);
            ProcList = Enum.GetNames(enumType).ToList().Select(x => new Proc
            { Index = i++, TrackType = (TrackTypeEnum)Enum.Parse(enumType, x), IsExist = false, Name = x }).ToList();
            foreach (var trackType in MaintenancePlans.Select(y =>
                (int)MaintenancePrograms.First(x => x.MaintenanceEnum == y.MaintenanceEnum).TrackTypeEnum))
            {
                ProcList[trackType].IsExist = true;
            }
            //计算工序关联股道
            foreach (var track in Tracks)
            {
                var index = (int)track.TrackTypeEnum;
                //ProcList[index].MachCnt++;
                ProcList[index].Tracks.Add(track);
            }
        }

        /// <summary>
        /// 所有工序的信息，用于查询
        /// </summary>
        public List<Proc> ProcList { get; set; }



        public int GetJobIdByTrainId(string trainId)
        {
            var train = MaintenancePlans.First(x => x.TrainId == trainId);
            return JobInfoDic[train.TrainId].JobId;
        }
    }
}
